package com.bstek.uflo.designer.deploy.impl;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;

import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.map.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import com.bstek.uflo.designer.deploy.DeployService;
import com.bstek.uflo.service.ProcessService;

/**
 * @author matt.yao@bstek.com
 * @since 1.0
 */
@Service(DeployService.BEAN_ID)
public class DeployServiceImpl implements DeployService {

	public static final String DEFAULT_FILE_NAME = "process.uflo.xml";
	public static final String POST_FILE_KEY = "processFile";

	@Autowired
	@Qualifier(ProcessService.BEAN_ID)
	private ProcessService processService;

	private String BOUNDARY = "---------------------------7d4a6d158c9";

	public String remoteDeploy(InputStream inputStream, String serverUrl){
		Assert.notNull(inputStream);
		Assert.notNull(serverUrl);
		try {
			this.deployProcessToServer(inputStream, serverUrl);
		} catch (Exception e) {
			return "流程部署失败！ 错误信息：\n" + e.getMessage().replaceAll("\r\r", "\n");
		}
		return null;
	}

	private void deployProcessToServer(InputStream is, String serverUrl) throws Exception {
		HttpURLConnection conn = buildHttpURLConnection(serverUrl);
		StringBuffer sb = new StringBuffer();
		sb.append("--");
		sb.append(this.BOUNDARY);
		sb.append("\r\n");
		sb.append("Content-Disposition: form-data; name=\"processFile\"; filename=\"process.uflo.xml\"\r\n");
		sb.append("Content-Type:application/x-zip-compressed\r\n\r\n");
		byte[] data = sb.toString().getBytes();
		byte[] end_data = ("\r\n--" + this.BOUNDARY + "--\r\n").getBytes();
		OutputStream os = conn.getOutputStream();
		os.write(data);

		byte[] buf2 = new byte[1024];
		int rn2;
		while ((rn2 = is.read(buf2, 0, 1024)) > 0) {
			os.write(buf2, 0, rn2);
		}
		os.write(end_data);
		os.flush();
		os.close();
		InputStream inputStream = conn.getInputStream();
		BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
		StringBuffer strBuf = new StringBuffer();
		String line = null;
		while ((line = reader.readLine()) != null) {
			strBuf.append(line);
		}
		reader.close();
		is.close();
		ObjectMapper mapper = new ObjectMapper();
		System.out.println(strBuf.toString());
		JsonNode rootNode = mapper.readTree(strBuf.toString());
		String result = rootNode.path("result").asText();
		if (result.equals("fail")) {
			JsonNode node = rootNode.path("error");
			String error = "部署操作失败。";
			if (node != null) {
				error = node.asText();
			}
			throw new RuntimeException(error);
		}
	}

	private HttpURLConnection buildHttpURLConnection(String serverUrl) throws Exception {
		URL url = new URL(serverUrl);
		HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
		urlConnection.setRequestMethod("POST");
		urlConnection.setDoOutput(true);
		urlConnection.setDoInput(true);
		urlConnection.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + this.BOUNDARY);
		urlConnection.setRequestProperty("connection", "Keep-Alive");
		urlConnection.setRequestProperty("Charsert", "UTF-8");
		urlConnection.setUseCaches(false);
		return urlConnection;
	}

	public void nativeDeploy(InputStream inputStream, long processId) {
		Assert.notNull(inputStream);
		Assert.notNull(processId);
		processService.deployProcess(inputStream, processId);
	}

	public void nativeDeploy(InputStream inputStream) {
		Assert.notNull(inputStream);
		processService.deployProcess(inputStream);
	}

}
